package com.ruoyi.websocket;

import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArraySet;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocketEndpoint {
    // concurrent包的线程安全Set, 用来存放每个客户端对应的WebSocket对象.
    private static final CopyOnWriteArraySet<WebSocketEndpoint> webSocketSet = new CopyOnWriteArraySet<>();
    //连接会话
    private Session session;
    // 连接用户ID
    private Long userId;
    // 连接标识符（用于退房等特定场景）
    private String socketId;

    //连接建立成功调用的方法
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        // 解析用户ID和socketId
        if (userId.contains("_")) {
            // 包含业务属性的连接，如 "123_checkout"
            String[] parts = userId.split("_");
            this.userId = Long.valueOf(parts[0]);
            this.socketId = userId; // 完整的socketId
        } else {
            // 普通连接，只有用户ID
            this.userId = Long.valueOf(userId);
            this.socketId = userId;
        }
        
        this.session = session;
        webSocketSet.add(this);
        log.info("有新连接加入,用户ID: {}, socketId: {}", this.userId, this.socketId);
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("回复用户ID: {}连接成功错误: {}", this.userId, e);
        }
    }

    // 连接关闭调用的方法
    @OnClose
    public void onClose() {
        log.info("有一连接断开, 用户ID: {}", this.userId);
        // 从set中删除
        webSocketSet.remove(this);
    }

    /**
     * 收到客户端消息后转发消息
     *
     * @param message 客户端发送过来的消息, 格式要求为: {"msg":"测试","groupId":1}
     * @param session 客户端session
     */
    @OnMessage(maxMessageSize = 999999L)
    public void onMessage(String message, Session session) {
        log.error("接收到用户ID: {}的消息:{}", this.userId, message);
    }

    /**
     * web-socket发生错误
     *
     * @param session 某个session
     * @param error   错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户ID: {}的session发生错误:{}", this.userId, error.getMessage());
    }

    public Long getUserId() {
        return this.userId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        WebSocketEndpoint webSocket = (WebSocketEndpoint) o;
        return Objects.equals(session, webSocket.session) &&
                Objects.equals(userId, webSocket.userId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(session, userId);
    }

    /**
     * 向客户端发送消息
     *
     * @param message 消息
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 发送消息给指定socket用户连接
     * @param userId 用户ID
     * @param message 消息
     * @throws IOException IO错误
     */
    public static void sendMessageToUser(Long userId, String message) throws IOException {
        for (WebSocketEndpoint socket : webSocketSet) {
            if (userId.equals(socket.getUserId())) {
                socket.sendMessage(message);
            }
        }
    }

    /**
     * 发送消息给指定socketId的连接
     * @param socketId 连接标识符
     * @param message 消息
     * @throws IOException IO错误
     */
    public static void sendMessageToSocketId(String socketId, String message) throws IOException {
        for (WebSocketEndpoint socket : webSocketSet) {
            if (socketId.equals(socket.socketId)) {
                socket.sendMessage(message);
                return; // 找到后立即返回
            }
        }
        log.warn("未找到socketId为 {} 的连接", socketId);
    }

    /**
     * 发送消息给所有连接
     * @param message 消息
     * @throws IOException IO错误
     */
    public static void sendMessageToAll(String message) throws IOException {
        for (WebSocketEndpoint socket : webSocketSet) {
            socket.sendMessage(message);
        }
    }
}
